package programmer;

import java.io.*;
import java.security.*;
import java.security.spec.*;

import javax.crypto.Cipher;

public class Encryption {

    private String publicKeyFile;

    public Encryption(String publicKeyFile) {
        this.publicKeyFile = publicKeyFile;
    }

    public String readFile(String f) throws IOException {
String text = new String();
        try {

            /*	Sets up a file reader to read the file passed on the command
            line one character at a time */
            FileReader input = new FileReader(f);

            /* Filter FileReader through a Buffered read to read a line at a
            time */
            BufferedReader bufRead = new BufferedReader(input);

            String line; 	// String that holds current file line
          

            // Read first line
            line = bufRead.readLine();
          

            // Read through file one line at time. Print line # and line
            while (line != null) {
                text += line + '\n';
                //System.out.println(line);\
                line = bufRead.readLine();
              
            }

            bufRead.close();

        } catch (ArrayIndexOutOfBoundsException e) {
            /* If no file was passed on the command line, this expception is
            generated. A message indicating how to the class should be
            called is displayed */
            System.out.println("Usage: java ReadFile filename\n");

        } catch (IOException e) {
            // If another exception is generated, print a stack trace
            e.printStackTrace();
        }

  
        return text;

    }

    public void encrypt(String file, String outfile) {
        try {

            /* import encoded public key */
            String text =  readFile(file);

            byte[] plainText = text.getBytes();
            FileInputStream keyfis = new FileInputStream(publicKeyFile);
            byte[] encKey = new byte[keyfis.available()];
            keyfis.read(encKey);

            keyfis.close();

            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);

            KeyFactory keyFactory = KeyFactory.getInstance("RSA");

            PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);

            System.out.println("\nStart encryption");
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] cipherText = cipher.doFinal(plainText);
            System.out.println("Finish encryption: ");
            System.out.println(new String(cipherText, "UTF8"));

            FileOutputStream sigfos = new FileOutputStream(outfile);

            sigfos.write(cipherText);
            System.out.println("CT: " + cipherText.length);

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    }

	public void GenerateSignature(String data, String sig,String privateKey) {

        /* Generate a DSA signature */
         try{

            /* Generate a key pair */

            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");

            keyGen.initialize(1024, random);

            KeyPair pair = keyGen.generateKeyPair();
            PrivateKey priv = pair.getPrivate();
            PublicKey pub = pair.getPublic();


            /* Create a Signature object and initialize it with the private key */

            Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");

            dsa.initSign(priv);

            /* Update and sign the data */

            FileInputStream fis = new FileInputStream(data);
            BufferedInputStream bufin = new BufferedInputStream(fis);
            byte[] buffer = new byte[1024];
            int len;
            while (bufin.available() != 0) {
                len = bufin.read(buffer);
                dsa.update(buffer, 0, len);
            }

            bufin.close();

            /* Now that all the data to be signed has been read in,
                    generate a signature for it */

            byte[] realSig = dsa.sign();


            /* Save the signature in a file */
            FileOutputStream sigfos = new FileOutputStream(sig);
            sigfos.write(realSig);

            sigfos.close();


            /* Save the public key in a file */
            byte[] key = pub.getEncoded();
            FileOutputStream keyfos = new FileOutputStream(privateKey);
            keyfos.write(key);

            keyfos.close();

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    }

	public void VerifySignature(String publickeyfile, String sigFile, String data) {

         try{

            /* import encoded public key */

            FileInputStream keyfis = new FileInputStream(publickeyfile);
            byte[] encKey = new byte[keyfis.available()];
            keyfis.read(encKey);

            keyfis.close();

            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);

            KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");
            PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);

            /* input the signature bytes */
            FileInputStream sigfis = new FileInputStream(sigFile);
            byte[] sigToVerify = new byte[sigfis.available()];
            sigfis.read(sigToVerify );

            sigfis.close();

            /* create a Signature object and initialize it with the public key */
            Signature sig = Signature.getInstance("SHA1withDSA", "SUN");
            sig.initVerify(pubKey);

            /* Update and verify the data */

            FileInputStream datafis = new FileInputStream(data);
            BufferedInputStream bufin = new BufferedInputStream(datafis);

            byte[] buffer = new byte[1024];
            int len;
            while (bufin.available() != 0) {
                len = bufin.read(buffer);
                sig.update(buffer, 0, len);
            }

            bufin.close();


            boolean verifies = sig.verify(sigToVerify);

            System.out.println("signature verifies: " + verifies);


        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
		}
    }
}
